package com.demo.topics;

import android.os.AsyncTask;
import com.demo.topics.data.Topic;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

/**
 * This fragment displays a search layout.
 * 
 * @author Ikai Lan <ikai@google.com>
 */
public class SearchFragment extends ListFragment {
	private static final String TAG = SearchFragment.class.getSimpleName();

	// UI Elements
	private Button mSearchButton;
	private EditText mTopicQuery;

	// Adapters
	private TopicListAdapter mTopicListAdapter;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.d(TAG, "Called onCreateView");

		// Inflate the fragment
		View topicSearchView = inflater.inflate(R.layout.fragment_topic_search,
				container, false);

		// Bind the UI elements to local instance variables
		mTopicQuery = (EditText) topicSearchView
				.findViewById(R.id.search_query_text);
		mSearchButton = (Button) topicSearchView
				.findViewById(R.id.search_button);

		// Bind the listeners
		mSearchButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// Fetch the current string in the edit buffer
				String queryString = mTopicQuery.getText().toString();

				// do the topic search
				doTopicSearch(queryString);
			}
		});

		// Bind the topic list UI element to the adapter
		mTopicListAdapter = new TopicListAdapter(getActivity(),
				R.layout.topic_list_row);
		setListAdapter(mTopicListAdapter);

		return topicSearchView;
	}
	
	/**
	 * This method calls the Topics API to fetch a list of topics
	 * 
	 * @param topicQuery
	 *            a topic string to send to the Topics API to fetch related MIDs
	 */
	private void doTopicSearch(String topicQuery) {
		Log.d(TAG, "Doing topic search with string: " + topicQuery);
        new FetchTopicsTask().execute(topicQuery);
	}
	
	/**
	 * This will handle the Topic being clicked. Make a YouTube API call and
	 * return the top 50 videos matching the topic.
	 */
	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		Topic topic = mTopicListAdapter.getItem(position);
		Log.d(TAG, "Topic selected: " + topic.getDisplayName() + " with MID: "
				+ topic.getMid());

		// Start a new Activity to show the topic's videos
		Intent searchResultsActivity = new Intent(getActivity(), SearchResultsActivity.class);
		
		// Pass it the topic data
		searchResultsActivity.putExtra(Topic.DISPLAY_NAME, topic.getDisplayName());
		searchResultsActivity.putExtra(Topic.DESCRIPTION, topic.getDescription());
		searchResultsActivity.putExtra(Topic.MID, topic.getMid());
		
		startActivity(searchResultsActivity);
	}

	/**
	 * List adapter for topic results when we execute the search
	 * 
	 * @author Ikai Lan <ikai@google.com>
	 * 
	 */
	private static class TopicListAdapter extends ArrayAdapter<Topic> {
		private Activity mContext;
		private int mLayoutResourceId;

		public TopicListAdapter(Context context, int textViewResourceId) {
			super(context, textViewResourceId);
			mContext = (Activity) context;
			mLayoutResourceId = textViewResourceId;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View rowView = convertView;
			if (rowView == null) {
				LayoutInflater inflater = mContext.getLayoutInflater();
				rowView = inflater.inflate(mLayoutResourceId, null);
			}

			// Make sure we are in bounds and draw the item
			if (position < getCount()) {
				TextView displayText = (TextView) rowView
						.findViewById(R.id.display_name);
				TextView description = (TextView) rowView
						.findViewById(R.id.description);

				Topic topic = getItem(position);
				displayText.setText(topic.getDisplayName());
				description.setText(topic.getDescription());
			}
			return rowView;
		}

	}

    /**
     * Asynchronous task for fetching topics from the Topics API, parsing the data, and updating the UI.
     */
    private class FetchTopicsTask extends AsyncTask<String, Void, List<Topic>> {

        public static final String FREEBASE_URL = "https://www.googleapis.com/freebase/v1/search?query=";

        @Override
        protected List<Topic> doInBackground(String... params) {
            // TODO: Make sure params takes only a single argument

            List<Topic> topics = new ArrayList<Topic>();
            try {

                // Call the Topics API and fetch a list of mids
                URL url = new URL(FREEBASE_URL + params[0]);
                URLConnection c = url.openConnection();

                // Parse JSON using Jackson
                ObjectMapper o = new ObjectMapper();
                JsonNode rootNode = o.readTree(c.getInputStream());
                ArrayNode results = (ArrayNode) rootNode.get("result");

                for(JsonNode result : results) {
                    Topic topic = new Topic();
                    topic.setDisplayName(result.get("name").asText());
                    topic.setMid(result.get("mid").asText());
                    topics.add(topic);
                }
            } catch (MalformedURLException e) {
                // In case we get some bad input, we should probably show something
            } catch (IOException e) {
                // TODO: in case we have no network
            }
            return topics;
        }

        @Override
        protected void onPostExecute(List<Topic> topics) {
            mTopicListAdapter.clear();
            mTopicListAdapter.addAll(topics);
        }
    }
}